module Hexena.Cmds.BloomLookup (run) where

import Data.Binary.Get
import Data.IFF
import Data.List (find)
import Data.Maybe
import Text.Printf
import qualified Data.ByteString as B
import qualified Data.ByteString.Lazy as BL

import Hexena.Internal.Blooming

-- ¦ Calculate all n-grams and check how many can be found
--
-- This will generate all n-grams from the byte string and check how
-- many of the n-grams can be found in the supplied bloom filter.
ngramifyLookup :: Blooming B.ByteString -> Int -> FilePath -> IO ()
ngramifyLookup bf n fn = do
  x <- B.readFile fn
  let lups = map (bloomingElem bf) $ takeN' n x
  let total = (B.length x - n + 1)
  let known = length $ filter id lups
  let ratio = fromIntegral known / fromIntegral total :: Double
  putStrLn $ "filename = " ++ fn
  putStrLn $ printf "\ttotal number of %d-grams  = %d $%06x" n total total
  putStrLn $ printf "\tknown number of %d-grams  = %d $%06x" n known known
  putStrLn $ printf "\tknown ration for %d-grams = %e" n ratio

-- | Load the Bloom filter
loadBloom :: T -> (Int, Blooming B.ByteString)
loadBloom iff = (fromIntegral nGram, fromJust $ loadBLOM hashFun iff)
    where hashFun = flip doHashes defaultHashes . B.unpack
          nGram = runGet getWord16be $ BL.fromChunks [content $ chunk $ fromJust $ find ((==) (chunkIdFromString "NGRM") . chunkId) $ parts $ chunk iff]

run :: [String] -> IO ()
run args = let blomID = chunkIdFromString "BLOM"
               findForm = find ((blomID ==) . chunkId) . parts . chunk . fromJust
           in do
             --iff <- parts $ chunk $ fromJust $ hasFormBLOM :: [T]
             iff <- fromByteString `fmap` B.getContents
             print iff
             let (ngrams, bloomFilter) = loadBloom $ fromJust iff
             if isNothing iff then
                 error "Can not get data from stdin."
              else
                 mapM_ (ngramifyLookup bloomFilter ngrams) args
